//
//  SketchSocketController.java
//  SketchServer
//
//  Created by Brian Hinch on 9/5/08.
//  Copyright 2008 Tellart. All rights reserved.
//

import java.io.*;
import java.net.*;
import javax.net.*;
import javax.swing.*;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

public class SketchSocketController extends SketchProtocolTransport {

    public static final String DISABLED_INTERFACE = "(disable)";

    public static final int TCP_PORT = 1025;
    private static final int MAX_CONCURRENT_CONNECTIONS = 10;
    private static final int IO_LOOP_DELAY = 1;

    /***********************************/

    private boolean started = false;
    private boolean connected = false;
    
    private ServiceAdvertiser advertiser;
    
    private String interfaceName;
	private ServerSocket sSocket;		//Main server socket
    private Socket cSocket;
    
    //the object to report new incoming messages to
    private int listenerSource;
    private SketchProtocolListener listener;
    private MyServer server;
	
    public SketchSocketController(int code, SketchProtocolListener lsnr) {
        super(code, lsnr);
    } //constructor
    
    /*
     * starts the controller
     *
     */
    public void start(String ifc) throws AlreadyStartedException, UnknownHostException, IOException  {
        if (started) throw new AlreadyStartedException();
        if (ifc.toLowerCase().equals(SketchSocketController.DISABLED_INTERFACE.toLowerCase())) return;

        interfaceName = ifc;
        InetAddress addr = openPort();
        
        started = true;
        connected = false;
        
        //start advertising over jmdns
        advertiser = new ServiceAdvertiser(
            addr,
            "nmiop",
            "tcp",
            TCP_PORT,
            "NADA Mobile remote IO pack server"
        );
        advertiser.start();
        
        //start the actual server
        server = new MyServer();
        server.start();
        
    } //start
    
    
    /*
     * stops the controller
     *
     */
    public void stop() {
        if (!started) return;
        started = false;
        connected = false;

        //stop advertising
        advertiser.stop();

        //shut down
        closePort();

        try {
            server.interrupt();
        } catch (Exception e) {
            System.err.println("Exception: " + e.getLocalizedMessage());
            e.printStackTrace(System.err);
        }
    }
    
    
    public boolean isStarted() {
        return started;
    } //isStarted
    
    
    public boolean isConnected() {
        return connected;
    } //isConnected
    
        
    private InetAddress openPort() throws UnknownHostException, IOException {
		
		InetAddress inetAddress = InetAddress.getByName(interfaceName);
        sSocket = ServerSocketFactory.getDefault().createServerSocket(TCP_PORT, MAX_CONCURRENT_CONNECTIONS, inetAddress);
        return inetAddress;
    } //openPort
    
    private void closePort() {
		System.out.println("SketchSocketController: closing port");
		if (sSocket == null) return;
		try {
			sSocket.close();
            cSocket.close();
		} catch (Exception e) { }
		sSocket = null;
        setIOStreams(null, null);
    } //closePort

    /************************************************************************/
    
    private class MyServer extends Thread {
        public MyServer() {
            super("SketchSocketController.MyServer");
        }
        
        public void run() {
            while (started) {
                try {
                    System.out.println("SketchSocketController.MyServer: waiting for a connection...");
                    
                    //block until a client connects to the server
                    cSocket = sSocket.accept();
                    System.out.println("SketchSocketController.MyServer: Conencted");
                    connected = true;
                    
                    //set up the IO streams
                    setIOStreams(cSocket.getInputStream(), cSocket.getOutputStream());
                    
                    //read data from the client
                    int bytesRead;
                    do {
                        //System.out.println("SketchSocketController.MyServer: Waiting for data from client...");
                        bytesRead = readInputBuffer();
                        System.out.println("SketchSocketController.MyServer: Read " + bytesRead + " bytes.");
                        try {
                            //System.out.println("SketchSocketController.MyServer: Pausing for " + IO_LOOP_DELAY + " ms");
                            Thread.sleep(IO_LOOP_DELAY);
                        } catch (InterruptedException ie) { }
                    } while (started && (bytesRead >= 0));
                    
                } catch (Exception e) {
                    System.err.println("Exception: " + e.getLocalizedMessage());
                    e.printStackTrace(System.err);
                }
                System.out.println("SketchSocketController.MyServer: Disconnected");
                connected = false;
                
            } //while started
            System.out.println("SketchSocketController.MyServer: Stopped");
                
        } //run
    } //inner class
    
}
